
// GoStructToTypeConverter.ts
type TypeMapping = {
  [key: string]: string | ((fieldName: string) => string);
};

export class GoStructConverter {
  private static defaultTypeMapping: TypeMapping = {
    'int': 'number',
    'int8': 'number',
    'int16': 'number',
    'int32': 'number',
    'int64': 'number',
    'uint': 'number',
    'float32': 'number',
    'float64': 'number',
    'string': 'string',
    'bool': 'boolean',
    'time.Time': 'string',  // 或 Date 根据项目需求调整
    'map': (keyType: string) => `Record<${keyType}, any>`, // 简化处理
    '[]': (innerType: string) => `${innerType}[]`,
  };

  static convert(goCode: string, customMapping?: TypeMapping): string {
    const mapping = { ...this.defaultTypeMapping, ...customMapping };
    const structRegex = /type\s+(\w+)\s+struct\s*{([^}]+)}/g;
    let result = '';

    let match;
    while ((match = structRegex.exec(goCode)) !== null) {
      const [_, structName, fieldsBlock] = match;
      result += `export type ${structName} = {\n`;
      result += this.processFields(fieldsBlock, mapping);
      result += `};\n\n`;
    }

    return result;
  }

  private static processFields(fieldsBlock: string, mapping: TypeMapping): string {
    const fieldLines = fieldsBlock.trim().split('\n');
    let output = '';

    for (const line of fieldLines) {
      const cleanedLine = line.replace(/\/\/.*$/, '').trim(); // 移除注释
      if (!cleanedLine) continue;

      const fieldMatch = cleanedLine.match(/(\w+)\s+([^`]+)(\s+`(.+)`)?/);
      if (!fieldMatch) continue;

      const [_, goFieldName, goType, , jsonTag] = fieldMatch;
      const { tsFieldName, optional } = this.parseJsonTag(jsonTag, goFieldName);
      const tsType = this.mapType(goType.trim(), mapping);

      output += `  ${tsFieldName}${optional ? '?' : ''}: ${tsType};\n`;
    }

    return output;
  }

  private static parseJsonTag(tag: string, defaultName: string):
    { tsFieldName: string, optional: boolean } {
    if (!tag) return { tsFieldName: defaultName, optional: false };

    const jsonTagMatch = tag.match(/json:"([^"]+)"/);
    if (!jsonTagMatch) return { tsFieldName: defaultName, optional: false };

    const [_, namePart] = jsonTagMatch;
    const [name, opts] = namePart.split(',');
    const optional = opts?.includes('omitempty') || false;

    return {
      tsFieldName: name || defaultName,
      optional
    };
  }

  private static mapType(goType: string, mapping: TypeMapping): string {
    // 处理指针类型
    if (goType.startsWith('*')) {
      return `${this.mapType(goType.slice(1), mapping)} | null`;
    }

    // 处理数组/slice
    if (goType.startsWith('[]')) {
      const innerType = this.mapType(goType.slice(2), mapping);
      return `Array<${innerType}>`;
    }

    // 处理 map 类型
    const mapMatch = goType.match(/map$$(\w+)$$(\w+)/);
    if (mapMatch) {
      const keyType = this.mapType(mapMatch[1], mapping);
      const valueType = this.mapType(mapMatch[2], mapping);
      return `Record<${keyType}, ${valueType}>`;
    }

    // 处理嵌套结构体
    if (/^[A-Z]/.test(goType) && !mapping[goType]) {
      return goType; // 假设已定义其他类型
    }

    // 处理已知类型
    const mapped = mapping[goType];
    return typeof mapped === 'function'
      ? mapped(goType)
      : mapped || 'any';
  }
}

// 示例用法
/*
const goCode = `
type User struct {
    ID        int       \`json:"id"\`
    Name      string    \`json:"name,omitempty"\`
    CreatedAt time.Time \`json:"created_at"\`
    Profile   *Profile  \`json:"profile"\`
}

type Profile struct {
    Age  int    \`json:"age"\`
    City string \`json:"city"\`
}
`;

console.log(GoStructConverter.convert(goCode));
*/


